---
title: "7. Paginate results"
---

As you might have noticed, the object returned from the `LaunchListQuery` is a `LaunchConnection`. This object has a list of launches, a pagination cursor, and a boolean to indicate whether more launches exist.

When using a cursor-based pagination system, it's important to remember that the cursor gives you a place where you can get all results after a certain spot, regardless of whether more items have been added in the interim.

In the previous section, you hardcoded the `SMALL` size argument directly in the GraphQL query, but you can also define arguments programmatically using variables. You will use them here to implement pagination.

## Add a `cursor` variable, and the `cursor` and `hasMore` fields

In `LaunchList.graphql`, add a `cursor` variable. In GraphQL, variables are prefixed with the dollar sign. 

Also add the `cursor` and `hasMore` fields to the query, as we will use them to paginate:

```graphql title="app/src/main/graphql/LaunchList.graphql"
query LaunchList($cursor: String) { # highlight-line
  launches(after: $cursor) { # highlight-line
    cursor # highlight-line
    launches {
      id
      site
      mission {
        name
        missionPatch(size: SMALL)
      }
    }
    hasMore # highlight-line
  }
}
```

You can experiment with GraphQL variables in Sandbox Explorer by using the pane under the main body of the operation named **Variables**. If you omit the `$cursor` variable, the server returns data starting from the beginning: 

<img src="images/explorer_cursor.png" alt="Explorer variables" class="screenshot"/>

## Fetch the next page when reaching the end of the list

Declare and remember a `cursor` var, initialized to `null`, and make the [`LauchedEffect` depend on it](https://developer.android.com/jetpack/compose/side-effects#launchedeffect). That way, the query will be re-executed every time the `cursor` changes.

Also keep a reference to `response` so we can access the `hasMore` and `cursor` fields further down.

```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchList.kt"
@Composable
fun LaunchList(onLaunchClick: (launchId: String) -> Unit) {
    var cursor: String? by remember { mutableStateOf(null) } // highlight-line
    var response: ApolloResponse<LaunchListQuery.Data>? by remember { mutableStateOf(null) } // highlight-line
    var launchList by remember { mutableStateOf(emptyList<LaunchListQuery.Launch>()) }
    LaunchedEffect(cursor) { // highlight-line
```

Pass the `cursor` to the `LaunchListQuery`, and add a special item at the end of the list which updates the `cursor` if `hasNext` is true. This will trigger a new query with the new cursor whenever the user scrolls to the end of the list, and `launchList` will be concatenated with the new results.

> **Note:** this is a basic implementation of pagination in Compose. In a real project you may use something more advanced, like the [Jetpack Paging library](https://developer.android.com/jetpack/compose/lists#large-datasets).

The whole function should look like this:
```kotlin title="app/src/main/java/com/example/rocketreserver/LaunchList.kt"
@Composable
fun LaunchList(onLaunchClick: (launchId: String) -> Unit) {
    var cursor: String? by remember { mutableStateOf(null) }
    var response: ApolloResponse<LaunchListQuery.Data>? by remember { mutableStateOf(null) }
    var launchList by remember { mutableStateOf(emptyList<LaunchListQuery.Launch>()) }
    LaunchedEffect(cursor) {
        response = apolloClient.query(LaunchListQuery(Optional.present(cursor))).execute() // highlight-line
        launchList = launchList + response?.data?.launches?.launches?.filterNotNull().orEmpty() // highlight-line
    }
    
    LazyColumn {
        items(launchList) { launch ->
            LaunchItem(launch = launch, onClick = onLaunchClick)
        }
        item { // highlight-line
            if (response?.data?.launches?.hasMore == true) { // highlight-line
                LoadingItem() // highlight-line
                cursor = response?.data?.launches?.cursor // highlight-line
            } // highlight-line
        } // highlight-line
    }
}
```

> Note that we wrap the `cursor` in an `Optional`: this is because this parameter can be omitted in the query. 

## Test scrolling

Click **Run**. You can now see all SpaceX launches back to their first FalconSat from Kwajalein Atoll!

Next, you'll [add a details view](08-add-a-details-view) that will allow you to book a seat on a launch.
